#include "bo3d.h"

// Create an Entity (instance of a discrete mesh). 
BBDECL Ogre::Entity* __stdcall o_createEntity(Ogre::SceneManager* scm, const char* entityName, const char* meshName, const char* groupName)
{
	Ogre::Entity* ent;
	Ogre::String rG;
	Ogre::String resG = Ogre::String(groupName);

	if(resG == "DEFAULT_RESOURCE_GROUP_NAME")
	{
		rG = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME;
	}
	else if(resG == "AUTODETECT_RESOURCE_GROUP_NAME")
	{
		rG = ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME;
	}
	else if(resG == "INTERNAL_RESOURCE_GROUP_NAME")
	{
		rG = ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME;
	}
	else
	{
		rG = resG;
	}
	
	try
	{
		ent = scm->createEntity(Ogre::String(entityName), Ogre::String(meshName), rG);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return ent;
}

// Gets the SceneNode at the root of the scene hierarchy. 
BBDECL Ogre::SceneNode* __stdcall o_getRootSceneNode(Ogre::SceneManager* scm)
{
	return scm->getRootSceneNode();
}

// set the Ambient Light
BBDECL void __stdcall o_setAmbientLight(Ogre::SceneManager* scm, boColourValue* col)
{
	try
	{
		scm->setAmbientLight(Ogre::ColourValue(col->red, col->green, col->blue, col->alpha));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Removes a camera from the scene. 
BBDECL void __stdcall o_destroyCamera(Ogre::SceneManager* scm, Ogre::Camera* cam)
{
	try
	{
		scm->destroyCamera(cam);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Removes (and destroys) all cameras from the scene. 
BBDECL void __stdcall o_destroyAllCameras(Ogre::SceneManager* scm)
{
	try
	{
		scm->destroyAllCameras();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Removes the light from the scene and destroys it based on a pointer. 
BBDECL void __stdcall o_destroyLight(Ogre::SceneManager* scm, Ogre::Light* light)
{
	try
	{
		scm->destroyLight(light);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Removes and destroys all lights in the scene. 
BBDECL void __stdcall o_destroyAllLights(Ogre::SceneManager* scm)
{
	try
	{
		scm->destroyAllLights();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Destroys a SceneNode. 
BBDECL void __stdcall o_destroySceneNode(Ogre::SceneManager* scm, Ogre::SceneNode* node)
{
	try
	{
		scm->destroySceneNode(node);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Removes & destroys an Entity from the SceneManager. 
BBDECL void __stdcall o_destroyEntity(Ogre::SceneManager* scm, Ogre::Entity* entity)
{
	try
	{
		scm->destroyEntity(entity);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Removes & destroys all Entities.
BBDECL void __stdcall o_destroyAllEntities(Ogre::SceneManager* scm)
{
	try
	{
		scm->destroyAllEntities();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Sets the general shadow technique to be used in this scene. 
BBDECL void __stdcall o_setShadowTechnique(Ogre::SceneManager* scm, int technique)
{
	try
	{
		scm->setShadowTechnique(Ogre::ShadowTechnique(technique));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

BBDECL void __stdcall o_setShadowTextureSize(Ogre::SceneManager* scm, int size)
{
	try
	{
		scm->setShadowTextureSize(size);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Sets the default maximum distance away from the camera that shadows will be visible. 
BBDECL void __stdcall o_sm_setShadowFarDistance(Ogre::SceneManager* scm, float distance)
{
	try
	{
		scm->setShadowFarDistance(Ogre::Real(distance));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Enables / disables a 'sky box' i.e. 
BBDECL void __stdcall o_setSkyBox(Ogre::SceneManager* scm, bool enable, const char* materialName, float distance, bool drawFirst, boQuaternion* orientation, const char* groupName)
{
	Ogre::Quaternion o;
	Ogre::String rG;
	Ogre::String resG = Ogre::String(groupName);

	if(resG == "DEFAULT_RESOURCE_GROUP_NAME")
	{
		rG = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME;
	}
	else if(resG == "AUTODETECT_RESOURCE_GROUP_NAME")
	{
		rG = ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME;
	}
	else if(resG == "INTERNAL_RESOURCE_GROUP_NAME")
	{
		rG = ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME;
	}
	else
	{
		rG = resG;
	}

	if(orientation == NULL)
	{
		o = Ogre::Quaternion::IDENTITY;
	}
	else
	{
		o = Ogre::Quaternion(Ogre::Real(orientation->w), Ogre::Real(orientation->x), Ogre::Real(orientation->y), Ogre::Real(orientation->z));
	}

	try
	{
		scm->setSkyBox(enable, Ogre::String(materialName), Ogre::Real(distance), drawFirst, o, rG);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Creates a RaySceneQuery  for this scene manager. 
BBDECL Ogre::RaySceneQuery* __stdcall o_createRayQuery(Ogre::SceneManager* scm, Ogre::Ray &r, unsigned long mask = 4294967295UL)
{
	Ogre::RaySceneQuery* rsq = scm->createRayQuery(r, mask);
	return rsq;
}

// Destroys a scene query of any type. 
BBDECL void __stdcall o_destroyQuery(Ogre::SceneManager* scm, Ogre::RaySceneQuery* rsq)
{
	try
	{
		scm->destroyQuery(rsq);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}


BBDECL float __stdcall o_getAverageFPS(Ogre::RenderWindow* win)
{
	return win->getAverageFPS();
}

BBDECL float __stdcall o_getBestFPS(Ogre::RenderWindow* win)
{
	return win->getBestFPS();
}

BBDECL float __stdcall o_getBestFrameTime(Ogre::RenderWindow* win)
{
	return win->getBestFrameTime();
}

BBDECL float __stdcall o_getLastFPS(Ogre::RenderWindow* win)
{
	return win->getLastFPS();
}

BBDECL float __stdcall o_getWorstFPS(Ogre::RenderWindow* win)
{
	return win->getWorstFPS();
}

BBDECL float __stdcall o_getWorstFrameTime(Ogre::RenderWindow* win)
{
	return win->getWorstFrameTime();
}